#include <chrono>
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <omp.h>

using namespace std;
typedef chrono::high_resolution_clock Clock;
const int SIZE = 100000;
const int LENGTH = 10000;

int main() {
  double *a = (double *)malloc(SIZE * sizeof(double));
  double **b = (double **)malloc(SIZE * sizeof(double *));
  double *c = (double *)malloc(LENGTH * sizeof(double));
  for (int i = 0; i < SIZE; i++) {
    b[i] = (double *)malloc(LENGTH * sizeof(double));
  }
  for (int i = 0; i < LENGTH; i++) {
    c[i] = 3.3 * i;
  }
  printf("omp %d %d\n", omp_get_max_threads(), omp_get_thread_num());
// #pragma omp parallel for
  for (int i = 0; i < SIZE; i++) {
    a[i] = 0;
    for (int j = 0; j < LENGTH; j++) {
      b[i][j] = 2.71828 * (i - j);
    }
  }

  auto startTime = Clock::now();
#pragma omp parallel for
  for (int i = 0; i < SIZE; i++) {
    double sum = 0.0;
    for (int j = 0; j < LENGTH; j++)
      sum += b[i][j] * c[j];
    a[i] = sum;
  }
  auto endTime = Clock::now();
  auto compTime =
      chrono::duration_cast<chrono::microseconds>(endTime - startTime);
  std::cout << "Computing time=" << compTime.count() / 1000 << " ms"
            << std::endl;

  for (int i = 0; i < SIZE; i += SIZE / 5) {
    printf("%lf\n", a[i]);
  }
  free(a);
  free(c);
  for (int i = 0; i < SIZE; i++) {
    free(b[i]);
  }
  free(b);
}